package prv.pursuivant.config.impl;

import static org.junit.Assert.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;

import org.junit.Before;
import org.junit.Test;

import prv.pursuivant.config.CategorySerializer;
import prv.pursuivant.core.AchievType;
import prv.pursuivant.core.AchievTypesTree;
import prv.pursuivant.core.AchievTypesTreeImpl;
import prv.pursuivant.core.impl.CategoryAchievType;
import prv.pursuivant.core.impl.KindImpl;
import prv.pursuivant.core.impl.NormalAchievType;
import prv.pursuivant.core.impl.NpcAchievType;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.internal.Lists;

public class XStreamCategorySerializerTest {

	private Injector injector;
	private AchievTypesTree dungeonsAndRaids;
	private String xmlText;

	@Before
	public void setUp() {
		AchievType q1a = new NpcAchievType("Anub'Rekhan", "562");
		AchievType q1b = new NpcAchievType("Maexxna", "562");
		AchievType q1c = new NpcAchievType("Grand Widow Faerlina", "562");
		AchievType q1 = new NormalAchievType("The Arachnid Quarter", "562",
				Lists.newArrayList(q1a.getId(), q1b.getId(), q1c.getId()));
		AchievType q2 = new NormalAchievType("The Construct Quarter", "564",
				Lists
						.newArrayList("564.Patchwerk", "564.Gluth",
								"564.Thaddius"));
		AchievType q3 = new NormalAchievType("The Plague Quarter", "566", Lists
				.newArrayList("566.Noth the Plaguebringer", "566.Loatheb",
						"566.Heigan the Unclean"));
		AchievType q4 = new NormalAchievType("The Military Quarter", "568",
				Lists.newArrayList("568.Instructor Razuvious",
						"568.The Four Horsemen", "568.Gothik the Harvester"));
		AchievType naxx = new NormalAchievType("The Fall of Naxxramas", "576",
				Lists.newArrayList(q1.getId(), q2.getId(), q3.getId(), q4
						.getId(), "572", "574"));
		dungeonsAndRaids = new AchievTypesTreeImpl(Lists.newArrayList(naxx, q1,
				q1a, q1b, q1c, q2, q3, q4), new CategoryAchievType(
				"Dungeons & Raids", "168", Lists.newArrayList("576")));

		xmlText = "<tree><root name=\"Dungeons &amp; Raids\" id=\"168\">"
				+ "<criteria>576</criteria></root><allTheAchievements>"
				+ "<achievement name=\"The Fall of Naxxramas\" id=\"576\">"
				+ "<criteria>562</criteria><criteria>564</criteria>"
				+ "<criteria>566</criteria><criteria>568</criteria>"
				+ "<criteria>572</criteria><criteria>574</criteria>"
				+ "</achievement>"
				+ "<achievement name=\"The Arachnid Quarter\" id=\"562\">"
				+ "<criteria>562.Anub&apos;Rekhan</criteria>"
				+ "<criteria>562.Maexxna</criteria>"
				+ "<criteria>562.Grand Widow Faerlina</criteria>"
				+ "</achievement>"
				+ "<npc name=\"Anub&apos;Rekhan\" parentId=\"562\"/>"
				+ "<npc name=\"Maexxna\" parentId=\"562\"/>"
				+ "<npc name=\"Grand Widow Faerlina\" parentId=\"562\"/>"
				+ "<achievement name=\"The Construct Quarter\" id=\"564\">"
				+ "<criteria>564.Patchwerk</criteria>"
				+ "<criteria>564.Gluth</criteria>"
				+ "<criteria>564.Thaddius</criteria></achievement>"
				+ "<achievement name=\"The Plague Quarter\" id=\"566\">"
				+ "<criteria>566.Noth the Plaguebringer</criteria>"
				+ "<criteria>566.Loatheb</criteria>"
				+ "<criteria>566.Heigan the Unclean</criteria>"
				+ "</achievement>"
				+ "<achievement name=\"The Military Quarter\" id=\"568\">"
				+ "<criteria>568.Instructor Razuvious</criteria>"
				+ "<criteria>568.The Four Horsemen</criteria>"
				+ "<criteria>568.Gothik the Harvester</criteria>"
				+ "</achievement></allTheAchievements></tree>";
		xmlText = xmlText.replaceAll(">\\s++<", "><");

		injector = Guice.createInjector(new XStreamCategorySerializerModule());
	}

	private String serialize(AchievTypesTree category) throws IOException {
		ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
		CategorySerializer serializer = injector
				.getInstance(CategorySerializer.class);
		serializer.writeTree(category, baos);
		String categoryText = baos.toString();
		categoryText = categoryText.replaceAll(">\\s++<", "><");
		return categoryText;
	}

	@Test
	public void shouldWriteCategory() throws IOException {
		String serialized = serialize(dungeonsAndRaids);
		assertEquals(xmlText, serialized);
	}

	@Test
	public void shouldReadCategory() throws IOException {
		final ByteArrayInputStream stream = new ByteArrayInputStream(xmlText
				.getBytes());
		CategorySerializer serializer = injector
				.getInstance(CategorySerializer.class);
		AchievTypesTree tree = serializer.readTree(stream);
		final AchievType maexxna = tree.findAchievTypeById("562.Maexxna");
		assertEquals("Maexxna", maexxna.getName());
		assertEquals("562.Maexxna", maexxna.getId());
		assertEquals(KindImpl.NPC, maexxna.getKind());
		assertEquals(0, maexxna.getCriteria().size());
	}

}
